package com.ruoyi.system.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.google.gson.Gson;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.core.domain.PageQuery;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.ruoyi.system.RSAUtils;
import com.ruoyi.system.domain.HiasActivationDevice;
import com.ruoyi.system.domain.bo.*;
import com.ruoyi.system.domain.to.HiasActivationSafeTo;
import com.ruoyi.system.domain.vo.HiasActivationRegisterVo;
import com.ruoyi.system.mapper.HiasActivationDeviceMapper;
import lombok.RequiredArgsConstructor;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import com.ruoyi.system.domain.vo.HiasActivationVo;
import com.ruoyi.system.domain.HiasActivation;
import com.ruoyi.system.mapper.HiasActivationMapper;
import com.ruoyi.system.service.IHiasActivationService;

import java.io.IOException;
import java.security.NoSuchAlgorithmException;
import java.security.interfaces.RSAPrivateKey;
import java.security.spec.InvalidKeySpecException;
import java.util.*;
import java.util.concurrent.locks.ReentrantLock;

/**
 * 【请填写功能名称】Service业务层处理
 *
 * @author ruoyi
 * @date 2024-03-09
 */
@RequiredArgsConstructor
@Service
public class HiasActivationServiceImpl implements IHiasActivationService {

    private final HiasActivationMapper baseMapper;
    private final HiasActivationDeviceMapper activationDeviceMapper;
    private final RabbitTemplate rabbitTemplate;

    private static ReentrantLock lock = new ReentrantLock();

    @Value("${hias.exchange.topicExchange}")
    private String exchangeName;


    /**
     * 查询【请填写功能名称】
     */
    @Override
    public HiasActivationVo queryById(Long id){
        return baseMapper.selectVoById(id);
    }

    /**
     * 查询【请填写功能名称】列表
     */
    @Override
    public TableDataInfo<HiasActivationVo> queryPageList(HiasActivationBo bo, PageQuery pageQuery) {
        LambdaQueryWrapper<HiasActivation> lqw = buildQueryWrapper(bo);
        Page<HiasActivationVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
        return TableDataInfo.build(result);
    }

    /**
     * 查询【请填写功能名称】列表
     */
    @Override
    public List<HiasActivationVo> queryList(HiasActivationBo bo) {
        LambdaQueryWrapper<HiasActivation> lqw = buildQueryWrapper(bo);
        return baseMapper.selectVoList(lqw);
    }

    private LambdaQueryWrapper<HiasActivation> buildQueryWrapper(HiasActivationBo bo) {
        Map<String, Object> params = bo.getParams();
        LambdaQueryWrapper<HiasActivation> lqw = Wrappers.lambdaQuery();
        lqw.eq(bo.getType() != null, HiasActivation::getType, bo.getType());
        lqw.eq(StringUtils.isNotBlank(bo.getDeviceId()), HiasActivation::getDeviceId, bo.getDeviceId());
        lqw.eq(StringUtils.isNotBlank(bo.getCode()), HiasActivation::getCode, bo.getCode());
        lqw.eq(StringUtils.isNotBlank(bo.getCodeState()), HiasActivation::getCodeState, bo.getCodeState());
        lqw.eq(bo.getMaturityTime() != null, HiasActivation::getMaturityTime, bo.getMaturityTime());
        return lqw;
    }

    /**
     * 新增【请填写功能名称】
     */
    @Override
    public Boolean insertByBo(HiasActivationBo bo) {
        HiasActivation add = BeanUtil.toBean(bo, HiasActivation.class);
        validEntityBeforeSave(add);
        boolean flag = baseMapper.insert(add) > 0;
        if (flag) {
            bo.setId(add.getId());
        }
        return flag;
    }

    /**
     * 修改【请填写功能名称】
     */
    @Override
    public Boolean updateByBo(HiasActivationBo bo) {
        HiasActivation update = BeanUtil.toBean(bo, HiasActivation.class);
        validEntityBeforeSave(update);
        return baseMapper.updateById(update) > 0;
    }

    /**
     * 保存前的数据校验
     */
    private void validEntityBeforeSave(HiasActivation entity){
        //TODO 做一些数据校验,如唯一约束
    }

    /**
     * 批量删除【请填写功能名称】
     */
    @Override
    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
        if(isValid){
            //TODO 做一些业务上的校验,判断是否需要校验
        }
        return baseMapper.deleteBatchIds(ids) > 0;
    }


    public int majorityElement(int[] nums) {
        Map<Integer, Integer> counts = new HashMap<Integer, Integer>();
        for (int num : nums) {
            if (!counts.containsKey(num)) {
                counts.put(num, 1);
            } else {
                counts.put(num, counts.get(num) + 1);
            }
        }
        return counts.get(nums);
    }

    @Override
    public R generateActivationCode(HiasActivationGenBo bo) {
        //
        rabbitTemplate.convertAndSend(exchangeName, "hias.info", "今天中午吃火锅");
        String code = UUID.randomUUID().toString();
        HiasActivation hiasActivation = new HiasActivation();
        hiasActivation.setCode(code);
        hiasActivation.setCodeState("0");//没用了
        hiasActivation.setLength((long) bo.getLength());
        hiasActivation.setType(bo.getType());
        hiasActivation.setMaturityTime(bo.getMaturityTime());
        hiasActivation.setMax(bo.getMax());
        hiasActivation.setVersion(bo.getVersion());
        baseMapper.insert(hiasActivation);

//        HiasActivationDevice hiasActivationDevice = new HiasActivationDevice();
//        hiasActivationDevice.setCode(code);
//        hiasActivationDevice.setState(0L);
//        activationDeviceMapper.insert(hiasActivationDevice);
        return R.ok();
    }

    @Override
    public R check(HiasActivationCheckBo bo) {
        List<HiasActivation> hiasActivations = new ArrayList<>();
        QueryWrapper wrapper = new QueryWrapper();
        wrapper.eq("code", bo.getCode());
        hiasActivations = baseMapper.selectList(wrapper);

        List<HiasActivationDevice> hiasActivationDevices = new ArrayList<>();
        QueryWrapper<HiasActivationDevice> wrapper1 = new QueryWrapper();
        wrapper1.eq("code", bo.getCode());
        wrapper1.eq("device_id", bo.getDeviceId());
        hiasActivationDevices = activationDeviceMapper.selectList(wrapper1);

        Date date = new Date();
        if (hiasActivationDevices.get(0).getHash().equals(bo.getHash())
            && date.before(hiasActivations.get(0).getMaturityTime())) {
            if (hiasActivationDevices.get(0).getState() == 0L) {
                hiasActivationDevices.get(0).setState(1L);
                hiasActivationDevices.get(0).setSerialNumber((long) bo.getSerialNumber());
                activationDeviceMapper.updateById(hiasActivationDevices.get(0));
            } else if (hiasActivationDevices.get(0).getState() == 1L
                && bo.getSerialNumber() - hiasActivationDevices.get(0).getSerialNumber() == hiasActivations.get(0).getLength()) {
                hiasActivationDevices.get(0).setSerialNumber((long) bo.getSerialNumber());
                activationDeviceMapper.updateById(hiasActivationDevices.get(0));
            } else {
                return R.fail("激活码已失效");
            }
            return R.ok();
        } else {
            return R.fail();
        }
    }

    @Override
    public HiasActivationSafeTo generateDeviceIdSafe(HiasActivationSafeBo safeBo) throws IOException, NoSuchAlgorithmException, InvalidKeySpecException {
        HiasActivationRegisterVo vo = new HiasActivationRegisterVo();
        vo.setLength(1);
        vo.setUuid("1");
        //将明文字符串json转成对应的对象
        Gson gson = new Gson();
        HiasActivationRegisterBo bo = gson.fromJson(safeBo.getSafeStr(), HiasActivationRegisterBo.class);
        //调用原先的接口处理逻辑
        HiasActivationSafeTo to = new HiasActivationSafeTo();
        if (bo.getCode() == null){
            to.setCode(100);
            to.setSafeStr(gson.toJson(vo));
            return to;
        }
        String uuid = UUID.randomUUID().toString();

        List<HiasActivation> hiasActivations = new ArrayList<>();
        QueryWrapper wrapper = new QueryWrapper();
        wrapper.eq( "code", bo.getCode());
        hiasActivations = baseMapper.selectList(wrapper);

        List<HiasActivationDevice> hiasActivationDevices = new ArrayList<>();
        QueryWrapper<HiasActivationDevice> wrapper1 = new QueryWrapper();
        wrapper1.eq("code", bo.getCode());
        hiasActivationDevices = activationDeviceMapper.selectList(wrapper1);

        if(hiasActivationDevices.size() < hiasActivations.get(0).getMax()){
            lock.lock();
            hiasActivationDevices = activationDeviceMapper.selectList(wrapper1);
            if(hiasActivationDevices.size() < hiasActivations.get(0).getMax()){
                HiasActivationDevice activationDevice = new HiasActivationDevice();
                activationDevice.setCode(bo.getCode());
                activationDevice.setHash(bo.getHash());
                activationDevice.setDeviceId(uuid);
                activationDevice.setState(0L);
                activationDeviceMapper.insert(activationDevice);
            }else{
                to.setMsg("激活码使用设备数已到上限");
                to.setSafeStr(gson.toJson(vo));
                return to;
            }
            lock.unlock();


            vo.setUuid(uuid);
            vo.setLength(Math.toIntExact(hiasActivations.get(0).getLength()));

            String str = gson.toJson(vo);

            to.setSafeStr(str);
            to.setCode(200);
            to.setMsg("激活成功");
            return to;
            //return R.ok(vo);
        }else{
            to.setMsg("激活码使用设备数达到上限");
            to.setSafeStr(gson.toJson(vo));
            return to;
            // return R.fail("激活码使用设备数达到上限");
        }
    }

    @Override
    public R generateActivationCodeSafe(HiasActivationSafeBo safeBo) throws IOException, NoSuchAlgorithmException, InvalidKeySpecException {
        //使用私钥把原先的加密文本解密成明文
        String privateKeyStr = RSAUtils.readPrivateKey();
        RSAPrivateKey privateKey = RSAUtils.getPrivateKey(privateKeyStr);
        String content = RSAUtils.privateDecrypt(safeBo.getSafeStr(), privateKey);
        //将明文字符串json转成对应的对象
        Gson gson = new Gson();
        HiasActivationGenBo genBo = gson.fromJson(content, HiasActivationGenBo.class);
        //调用原先的接口处理逻辑
        return generateActivationCode(genBo);
    }

    @Override
    public R checkSafe(HiasActivationSafeBo safeBo) throws IOException, NoSuchAlgorithmException, InvalidKeySpecException {
        //使用私钥把原先的加密文本解密成明文
        String privateKeyStr = RSAUtils.readPrivateKey();
        RSAPrivateKey privateKey = RSAUtils.getPrivateKey(privateKeyStr);
        String content = RSAUtils.privateDecrypt(safeBo.getSafeStr(), privateKey);
        //将明文字符串json转成对应的对象
        Gson gson = new Gson();
        HiasActivationCheckBo checkBo = gson.fromJson(content, HiasActivationCheckBo.class);
        //调用原先的接口处理逻辑
        return check(checkBo);
    }
}
